/*
 * Copyright (c) 2024 Huawei Technologies Co.,Ltd.
 *
 * openGauss is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *
 * http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 * ---------------------------------------------------------------------------------------
 *
 * imcs_flush_insert.h
 * routines to support flush
 *
 * IDENTIFICATION
 * src/include/access/imcs/imcs_flush_insert.h
 *
 * ---------------------------------------------------------------------------------------
 */
#ifndef IMCS_FLUSH_INSERT_H
#define IMCS_FLUSH_INSERT_H

#include "imcs_am.h"
#include "access/cstore_delta.h"
#include "imcs_vector.h"
#include "imcs_minmax_func.h"
#include "storage/cstore/cstore_compress.h"
#include "storage/spin.h"
#include "imcs_ctlg.h"
#include "catalog/gs_imcs.h"

class IMCSFlushInsert : public BaseObject {
public:
    IMCSFlushInsert(_in_ Relation relation, _in_ ResultRelInfo *result_rel_info, _in_ bool is_update_cu,
        _in_ Plan *plan, _in_ ImcsMemInfoArg *argmem_info, TupleDesc tupdesc_with_ctid);

    virtual ~IMCSFlushInsert();
    virtual void Destroy();

    void BeginBatchInsert();

    // Append batch to existing CU
    void AppendImcus(IMCU *old_cu, IMCUDesc *old_cu_desc, IMCU *new_cu, IMCUDesc *new_cu_desc,
        bool &use_exist_imcu_cache_desc, int col_idx);
    void BatchInsertCommon(IMCSBulkloadRows *batch_row_ptr, IMCU **old_cus = nullptr,
        IMCUDesc **old_cus_descs = nullptr, bool multithread = false, IMCSDesc *imcs_desc = NULL);
    void UpdateAppendedImcuBuf(IMCU *old_cu, IMCU *new_cu, IMCUDesc *old_desc, IMCUDesc *new_desc,
        bool is_old_desc_null_cu);
    void UpdateAppendedImcuDesc(IMCUDesc *old_cu_desc, IMCUDesc *new_cu_desc, int col_idx);
    void UpdateAppendedImcu(IMCU *dest_cu, IMCU *src_cu, IMCUDesc *dest_cu_desc, IMCUDesc *src_cu_desc,
        bool is_old_desc_null_cu);
    void CopyToCuBm(IMCU *dest_cu, int offset_in_dest_bm, IMCU *src_cu, int raw_cnt_in_src, bool src_null_cu,
        bool src_has_null);

    void InitInsertMemArg(Plan *plan, ImcsMemInfoArg *argmem_info);

    Relation m_imi_relation;
    TupleDesc td_tid;
    uint32 m_imi_cur_cuid;
    ImcsMemInfoArg *m_imi_cstor_insert_mem;

    CacheSlotId_t get_slot_id()
    {
        return m_slot_id;
    }

private:
    typedef void (IMCSFlushInsert::*m_formCUFunc)(int, IMCSBulkloadRows *, IMCUDesc *, IMCU *);
    struct FormCUFuncArray {
        m_formCUFunc col_form_cu[2];
    };
    FormCUFuncArray *m_form_cu_func_array;
    bool m_is_update;
    ImcsFuncSetMinMax *m_set_min_max_funcs;
    IMCUDesc **m_cu_desc_pptr;
    IMCU **m_cu_pptr;
    IMCUStorage **m_cu_storage;
    compression_options *m_cu_compress_options;
    cu_tmp_compress_info m_cu_temp_info;
    int m_full_cu_size;
    int m_delta_rows_threshold;
    int16 m_compress_modes;
    CacheSlotId_t m_slot_id;

    // Form Routines
    IMCU *FlushInsertFormCu(int col, IMCSBulkloadRows *batch_row_ptr, IMCUDesc *cu_desc_ptr,
        TupleDesc tupdesc_with_ctid, bool compress);
    Size FlushInsertFormCutInitMem(IMCU *cu_ptr, IMCSBulkloadRows *batch_row_ptr, int col, bool has_null);
    void FlushInsertFormCutCopyMem(IMCU *cu_ptr, IMCSBulkloadRows *batch_row_ptr, IMCUDesc *cu_desc_ptr, Size dtSize,
        int col, bool has_null);
    template <bool hasNull>
    void FlushInsertFormCut(int col, IMCSBulkloadRows *batch_row_ptr, IMCUDesc *cu_desc_ptr, IMCU *cu_ptr);
    template <bool hasNull>
    void FlushInsertFormCutNumeric(int col, IMCSBulkloadRows *batch_row_ptr, IMCUDesc *cu_desc_ptr, IMCU *cu_ptr);
    template <bool hasNull>
    void FlushInsertFormCutNumString(int col, IMCSBulkloadRows *batch_row_ptr, IMCUDesc *cu_desc_ptr, IMCU *cu_ptr);
    template <bool bpcharType, bool hasNull, bool has_MinMax_func>
    bool FlushInsertFormNumberStringCu(int col, IMCSBulkloadRows *batch_row_ptr, IMCUDesc *cu_desc_ptr, IMCU *cu_ptr);

    template <bool hasNull>
    bool FlushInsertTryFormNumberStringCu(int col, IMCSBulkloadRows *batch_row_ptr, IMCUDesc *cu_desc_ptr,
        IMCU *cu_ptr, uint32 atttypid);
    void FlushInsertInitFuncPtr();
    void FlushInsertInitColSpaceAlloc();
    bool FlushInsertTryEncodeNumeric(int col, IMCSBulkloadRows *batch_row_ptr, IMCUDesc *cu_desc_ptr, IMCU *cu_ptr,
        bool has_null);
    inline void FlushInsertSetFormCuFuncArray(Form_pg_attribute attr, int col);
};

#endif
